﻿//---------------------------------------------------------------------------
#pragma hdrstop

#include "stdafx.h"
#include "Class.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)

Swarm_Class::SetChord(int Chord1, int Chord2, int Chord3, int Chord4)
{
	this->Chord[0] = Chord1;
	this->Chord[1] = Chord2;
	this->Chord[2] = Chord3;
	this->Chord[3] = Chord4;
}

Swarm_Class::Initial()
{
	this->MaxNoteValue = 0;
	this->MinNoteValue = 0;
	this->MaxPhraseValue = 0;
    this->MinPhraseValue = 0;

	for(int Gi=0; Gi<BestParticleNum; Gi++) //跑Particle
	{
		this->G_Best[Gi].Fitness = -999999999;
	}

	for(int i=0; i<ParticleNum; i++) //跑Particle
	{
		this->Particle[i].Fitness = -999999999;
		this->Particle[i].P_Best_Fitness = -999999999;

		for(int j=0; j<4; j++) //跑Phrase
		{
			this->Particle[i].Phrase[j].Phrase_Fitness = 0;
			this->Particle[i].P_Best_Phrase[j].Phrase_Fitness = 0;

			for(int k=0; k<OneSectionNoteNum; k++) //Note
			{
				Application->ProcessMessages();
				this->Particle[i].P_Best_Phrase[j].Note[k].Live = false;
				this->Particle[i].P_Best_Phrase[j].Note[k].Pos = 0;
				this->Particle[i].P_Best_Phrase[j].Note[k].Vec = 0;
				this->Particle[i].P_Best_Phrase[j].Note[k].Weight = 0;

				//一開始是否活著的機率
				this->Particle[i].Phrase[j].Note[k].Live = RandRange(0, 1) < 0.7 ? true : false;
				//位置給亂數
				//this->Particle[i].Phrase[j].Note[k].Pos = (int)(RandRange(-4, 9) + 0.5);
				this->Particle[i].Phrase[j].Note[k].Pos = (int)(RandRange(0, 6) + 0.5);
			}
		}
	}
}

Swarm_Class::GetFitness()
{
	AnsiString ChordNote[4];  //0是全部
	int TempPos, ComparePos, Leap, TempFitness;
	Particle_Class TempParticle;

	for(int i=0; i<ParticleNum; i++) //跑Particle
	{
		this->Particle[i].Fitness = 0;

		for(int j=0; j<4; j++) //跑Phrase
		{
			Application->ProcessMessages();
            switch(this->Chord[j])
			{
				case 1:
					ChordNote[0] = "0,7,2,9,-3,4";
					ChordNote[1] = "0,7";   //Do
					ChordNote[2] = "2,9";   //Me
					ChordNote[3] = "-3,4";  //So
					break;

				case 2:
					ChordNote[0] = "1,8,-4,3,-2,5";
					ChordNote[1] = "1,8";   //Re
					ChordNote[2] = "-4,3";  //Fa
					ChordNote[3] = "-2,5";  //La
					break;

				case 3:
					ChordNote[0] = "2,9,-3,4,-1,7";
					ChordNote[1] = "2,9";   //Me
					ChordNote[2] = "-3,4";  //So
					ChordNote[3] = "-1,7";  //Si
					break;

				case 4:
					ChordNote[0] = "-4,3,-2,5,0,7";
					ChordNote[1] = "-4,3";  //Fa
					ChordNote[2] = "-2,5";  //La
					ChordNote[3] = "0,7";   //Do
					break;

				case 5:
					ChordNote[0] = "-3,4,-1,7,1,8";
					ChordNote[1] = "-3,4";  //So
					ChordNote[2] = "-1,7";  //Si
					ChordNote[3] = "1,8";   //Re
					break;

				case 6:
					ChordNote[0] = "-2,5,0,7,2,9";
					ChordNote[1] = "-2,5";  //La
					ChordNote[2] = "0,7";   //Do
					ChordNote[3] = "2,9";   //Me
					break;

				case 7:
					ChordNote[0] = "-1,7,1,8,-4,3";
					ChordNote[1] = "-1,7";  //Si
					ChordNote[2] = "1,8";   //Re
					ChordNote[3] = "-4,3";  //Fa
					break;
			}

			this->Particle[i].Phrase[j].Phrase_Fitness = 0;
			for(int k=0; k<OneSectionNoteNum; k++) //Note
			{
				this->Particle[i].Phrase[j].Note[k].Weight = 0;

				if(this->Particle[i].Phrase[j].Note[k].Live) //如果還活著
				{
					TempPos = (int)(this->Particle[i].Phrase[j].Note[k].Pos + 0.5);

					//2 The note is a chord note 13300 44 這個音在和弦裡面
					if( word_existence(IntToStr(TempPos), ChordNote[0]) )
					{
						this->Particle[i].Phrase[j].Note[k].Weight += 44;
					}

					//3 The note is a chord note (chord root note) 284 504 這個音在和弦（第1個音）裡面
					if( word_existence(IntToStr(TempPos), ChordNote[1]) )
					{
						this->Particle[i].Phrase[j].Note[k].Weight += 504;
					}

					//4 The note is a chord note (chord 2nd note) 223 234 這個音在和弦（第2個音）裡面
					if( word_existence(IntToStr(TempPos), ChordNote[2]) )
					{
						this->Particle[i].Phrase[j].Note[k].Weight += 234;
					}

					//5 The note is a chord note (chord 3rd note) 304 95 這個音在和弦（第3個音）裡面
					if( word_existence(IntToStr(TempPos), ChordNote[3]) )
					{
						this->Particle[i].Phrase[j].Note[k].Weight += 95;
					}


					if( j == 3 ) //如果是終止小節
					{
						//6 The note of phrase cadence is the chord note 331 846   phrases 一小段樂句  Cadence : 終止式 終止式的小節裡（4,8,12...小節） 的音是和弦音
						if( word_existence(IntToStr(TempPos), ChordNote[0]) )
						{
							this->Particle[i].Phrase[j].Note[k].Weight += 846;
						}
						//7 The note of phrase cadence is not the chord note 1397 -168 終止式的小節裡（4,8,12...小節） 的音不是和弦音
						else
						{
							this->Particle[i].Phrase[j].Note[k].Weight += -168;
						}
					}

					if( k == 0 ) //如果是小節裡面的第1個音
					{
						//8 The note is the first note in a phrase and is a chord note (chord root note) 156 745 小節裡的第1個音是和弦音（第1個音）
						if( word_existence(IntToStr(TempPos), ChordNote[1]) )
						{
							this->Particle[i].Phrase[j].Note[k].Weight += 745;
						}
						//9 The note is the first note in a phrase and is a chord note (chord 2nd note) 132 839 小節裡的第1個音是和弦音（第2個音）
						if( word_existence(IntToStr(TempPos), ChordNote[2]) )
						{
							this->Particle[i].Phrase[j].Note[k].Weight += 839;
						}
						//10 The note is the first note in a phrase and is a chord note (chord 3rd note) 192 885 小節裡的第1個音是和弦音（第3個音）
						if( word_existence(IntToStr(TempPos), ChordNote[3]) )
						{
							this->Particle[i].Phrase[j].Note[k].Weight += 885;
						}
					}

					if( k == OneSectionNoteNum-1 ) //如果是小節裡面的最後一個音
					{
						//11 The note is the last note in a phrase and is a chord note (chord root note) 135 3584 小節裡的最後一個音是和弦音（第1個音）
                        if( word_existence(IntToStr(TempPos), ChordNote[1]) )
						{
							this->Particle[i].Phrase[j].Note[k].Weight += 3584;
						}
						//12 The note is the last note in a phrase and is a chord note (chord 2nd note) 149 380 小節裡的最後一個音是和弦音（第2個音）
						if( word_existence(IntToStr(TempPos), ChordNote[2]) )
						{
							this->Particle[i].Phrase[j].Note[k].Weight += 380;
						}
						//13 The note is the last note in a phrase and is a chord note (chord 3rd note) 149 1372 小節裡的最後一個音是和弦音（第3個音）
						if( word_existence(IntToStr(TempPos), ChordNote[3]) )
						{
							this->Particle[i].Phrase[j].Note[k].Weight += 1372;
						}
						//14 The note is the last note in a phrase and is a chord note (chord 4th note) 101 1687 小節裡的最後一個音是和弦音（第4個音？？？）
                    }

					if( k % 2 == 0 ) //如果是在重音拍上0 2 4 6
					{
						//15 Chord note on stress 557 441 這個音是和弦音而且是在重音上(最快八分音符來說就是1,2,3,4拍)
                        if( word_existence(IntToStr(TempPos), ChordNote[0]) )
						{
							this->Particle[i].Phrase[j].Note[k].Weight += 441;
						}
						//16 Invalid note on stress 175 -2216 重音上有不是和弦的音？？？
						else
						{
							this->Particle[i].Phrase[j].Note[k].Weight += -2216;
						}
					}

					ComparePos = -100;  //表示沒找到
					//先找出後面一個音是哪個音
					for(int PhrasePlus=0; j+PhrasePlus<4; PhrasePlus++)
					{
                        if(ComparePos != -100)  //有找到了
						{break;}

						if(PhrasePlus == 0) //還沒有跳下一個Phrase
						{
							for(int NotePlus=1; k+NotePlus<OneSectionNoteNum; NotePlus++)
							{
								if(ComparePos != -100)  //有找到了
								{break;}

								if( this->Particle[i].Phrase[j+PhrasePlus].Note[k+NotePlus].Live )   //如果有活著
								{
									ComparePos = (int)(this->Particle[i].Phrase[j+PhrasePlus].Note[k+NotePlus].Pos + 0.5);
								}
							}
						}
						else   //Phrase已經跳了
						{
							for(int CurrentNote=0; CurrentNote<OneSectionNoteNum; CurrentNote++)
							{
								if(ComparePos != -100)  //有找到了
								{break;}

								if( this->Particle[i].Phrase[j+PhrasePlus].Note[CurrentNote].Live )   //如果有活著
								{
									ComparePos = (int)(this->Particle[i].Phrase[j+PhrasePlus].Note[CurrentNote].Pos + 0.5);
								}
							}
						}
					}

					//////consider the scales and leaps in order to generate smooth and rational melodies. scales 音階   leap  跳進
					Leap = ComparePos - (int)(this->Particle[i].Phrase[j].Note[k].Pos + 0.5);
					if(ComparePos != -100)   //有找到
					{
						switch(Leap)
						{
							//25 Process of scale (ascending) 1523 40   後面比現在的高1
							case 1:
								this->Particle[i].Phrase[j].Note[k].Weight += 40;
								break;
							//26 Process of scale (descending) 1980 223 連續的音（類似543 345等等）  後面比現在的低1
							case -1:
								this->Particle[i].Phrase[j].Note[k].Weight += 223;
								break;
							//27 Process of third leap (ascending) 1971 -33 	他後面的往上跳三度（1->3）
							case 2:
								this->Particle[i].Phrase[j].Note[k].Weight += -33;
								break;
							//29 Process of third leap (descending) 239 176
							case -2:
								this->Particle[i].Phrase[j].Note[k].Weight += 176;
								break;
							//31 Process of fourth leap (ascending) 259 -249
							case 3:
								this->Particle[i].Phrase[j].Note[k].Weight += -2216;
								break;
							//33 Process of fourth leap (descending) 112 36
							case -3:
								this->Particle[i].Phrase[j].Note[k].Weight += 36;
								break;
							//35 Process of fifth leap (ascending) 201 634
							case 4:
								this->Particle[i].Phrase[j].Note[k].Weight += 634;
								break;
							//37 Process of fifth leap (descending) 255 54
							case -4:
								this->Particle[i].Phrase[j].Note[k].Weight += 54;
								break;
							//39 Process of sixth leap (ascending) 78 10
							case 5:
								this->Particle[i].Phrase[j].Note[k].Weight += 10;
								break;
							//41 Process of sixth leap (descending) 388 19
							case -5:
								this->Particle[i].Phrase[j].Note[k].Weight += 19;
								break;
						}
					}

                    ComparePos = -100;  //表示沒找到
					//先找出前面一個音是哪個音
					for(int PhrasePlus=0; j+PhrasePlus>=0; PhrasePlus--)
					{
                        if(ComparePos != -100)  //有找到了
						{break;}

						if(PhrasePlus == 0) //還沒有跳上一個Phrase
						{
							for(int NotePlus=-1; k+NotePlus>=0; NotePlus--)
							{
								if(ComparePos != -100)  //有找到了
								{break;}

								if( this->Particle[i].Phrase[j+PhrasePlus].Note[k+NotePlus].Live )   //如果有活著
								{
									ComparePos = (int)(this->Particle[i].Phrase[j+PhrasePlus].Note[k+NotePlus].Pos + 0.5);
								}
							}
						}
						else   //Phrase已經跳了
						{
							for(int CurrentNote=OneSectionNoteNum-1; CurrentNote>=0; CurrentNote--)
							{
								if(ComparePos != -100)  //有找到了
								{break;}

								if( this->Particle[i].Phrase[j+PhrasePlus].Note[CurrentNote].Live )   //如果有活著
								{
									ComparePos = (int)(this->Particle[i].Phrase[j+PhrasePlus].Note[CurrentNote].Pos + 0.5);
								}
							}
						}
					}

					//////consider the scales and leaps in order to generate smooth and rational melodies. scales 音階   leap  跳進
					Leap = ComparePos - (int)(this->Particle[i].Phrase[j].Note[k].Pos + 0.5);
					if(ComparePos != -100)   //有找到
					{
						switch(Leap)
						{
							//28 Subsequent process of third leap (ascending) 198 -307 他前面的往上跳三度（1->3）
							case 2:
								this->Particle[i].Phrase[j].Note[k].Weight += -307;
								break;
							//30 Subsequent process of third leap (descending) 358 -55
							case -2:
								this->Particle[i].Phrase[j].Note[k].Weight += -55;
								break;
							//32 Subsequent process of fourth leap (ascending) 134 1085
							case 3:
								this->Particle[i].Phrase[j].Note[k].Weight += 1085;
								break;
							//34 Subsequent process of fourth leap (descending) 231 81
							case -3:
								this->Particle[i].Phrase[j].Note[k].Weight += 81;
								break;
							//36 Subsequent process of fifth leap (ascending) 119 99
							case 4:
								this->Particle[i].Phrase[j].Note[k].Weight += 99;
								break;
							//38 Subsequent process of fifth leap (descending) 104 77
							case -4:
								this->Particle[i].Phrase[j].Note[k].Weight += 77;
								break;
							//40 Subsequent process of sixth leap (ascending) 247 34
							case 5:
								this->Particle[i].Phrase[j].Note[k].Weight += 34;
								break;
							//42 Subsequent process of sixth leap (descending) 531 7
							case -5:
								this->Particle[i].Phrase[j].Note[k].Weight += 7;
								break;
						}
					}
				}

				//這個Note的Weight已經算完了
				this->Particle[i].Phrase[j].Phrase_Fitness += this->Particle[i].Phrase[j].Note[k].Weight;

				if(this->Particle[i].Phrase[j].Note[k].Weight > this->MaxNoteValue)
				{
					this->MaxNoteValue = this->Particle[i].Phrase[j].Note[k].Weight;
				}
				if(this->Particle[i].Phrase[j].Note[k].Weight < this->MinNoteValue)
				{
					this->MinNoteValue = this->Particle[i].Phrase[j].Note[k].Weight;
				}

			}
			//這個Phrase的Fitness已經算完了
			this->Particle[i].Fitness += this->Particle[i].Phrase[j].Phrase_Fitness;

			if(this->Particle[i].Phrase[j].Phrase_Fitness > this->MaxPhraseValue)
			{
				this->MaxPhraseValue = this->Particle[i].Phrase[j].Phrase_Fitness;
			}
			if(this->Particle[i].Phrase[j].Phrase_Fitness < this->MinPhraseValue)
			{
				this->MinPhraseValue = this->Particle[i].Phrase[j].Phrase_Fitness;
			}
		}

		//P Best
		if(	this->Particle[i].Fitness > this->Particle[i].P_Best_Fitness)
		{
			this->Particle[i].P_Best_Fitness = this->Particle[i].Fitness;
			this->Particle[i].P_Best_Phrase[0] = this->Particle[i].Phrase[0];
			this->Particle[i].P_Best_Phrase[1] = this->Particle[i].Phrase[1];
			this->Particle[i].P_Best_Phrase[2] = this->Particle[i].Phrase[2];
			this->Particle[i].P_Best_Phrase[3] = this->Particle[i].Phrase[3];
		}

		//G Best
        if(	this->Particle[i].Fitness > this->G_Best[BestParticleNum-1].Fitness) //有沒有比best最小的大
		{
            //取代
			this->G_Best[BestParticleNum-1].Fitness = this->Particle[i].Fitness;
			this->G_Best[BestParticleNum-1] = this->Particle[i];

			//排序
			for(int Gi=BestParticleNum-1; Gi>=1; Gi--) //跑BEST Particle  從最下面的開始比
			{
				if(	this->G_Best[Gi].Fitness > this->G_Best[Gi-1].Fitness ) //如果下面的有比上面的大
				{
                    //對調
					TempFitness = this->G_Best[Gi].Fitness;
					TempParticle = this->G_Best[Gi];

					this->G_Best[Gi].Fitness = this->G_Best[Gi-1].Fitness;
					this->G_Best[Gi] = this->G_Best[Gi-1];

					this->G_Best[Gi-1].Fitness = TempFitness;
					this->G_Best[Gi-1] = TempParticle;
				}
			}
		}
	}
}

void Swarm_Class::Move(bool EPSO)
{
	float W1, Wp, Wg;  //移動的權重植
	W1 = 0.5;
	Wp = 1.5;
	Wg = 1.5;

	for(int i=0; i<ParticleNum; i++) //跑Particle
	{
		for(int j=0; j<4; j++) //跑Phrase
		{
			for(int k=0; k<OneSectionNoteNum; k++) //Note
			{
				Application->ProcessMessages();
				//如果這點還活著
				if( this->Particle[i].Phrase[j].Note[k].Live )
				{
					if(EPSO)
					{
						W1 = 0.5 + Tau * RandG((float)0,(float)1);
						Wp = 1.5 + Tau * RandG((float)0,(float)1);
						Wg = 1.5 + Tau * RandG((float)0,(float)1);
					}

					//計算Vec
					this->Particle[i].Phrase[j].Note[k].Vec *= W1;
					//PBest 如果這點還活著
					if( this->Particle[i].P_Best_Phrase[j].Note[k].Live )
					{
						if(EPSO)
						{
                        	this->Particle[i].Phrase[j].Note[k].Vec += Wp * RandRange(0,1) *
							( this->Particle[i].P_Best_Phrase[j].Note[k].Pos + Tau * RandG((float)0,(float)1) - this->Particle[i].Phrase[j].Note[k].Pos );
						}
						else
						{
							this->Particle[i].Phrase[j].Note[k].Vec += Wp * RandRange(0,1) *
							( this->Particle[i].P_Best_Phrase[j].Note[k].Pos - this->Particle[i].Phrase[j].Note[k].Pos );
						}
					}

					//GBest 如果這點還活著
					if( this->G_Best[0].Phrase[j].Note[k].Live )
					{
						if(EPSO)
						{
							this->Particle[i].Phrase[j].Note[k].Vec += Wg * RandRange(0,1) *
							( this->G_Best[0].Phrase[j].Note[k].Pos + Tau * RandG((float)0,(float)1) - this->Particle[i].Phrase[j].Note[k].Pos );
						}
						else
						{
							this->Particle[i].Phrase[j].Note[k].Vec += Wg * RandRange(0,1) *
							( this->G_Best[0].Phrase[j].Note[k].Pos - this->Particle[i].Phrase[j].Note[k].Pos );
						}
					}

					//開始移動
					this->Particle[i].Phrase[j].Note[k].Pos += this->Particle[i].Phrase[j].Note[k].Vec;
				}
			}
		}
	}
}

void Swarm_Class::Crossover()
{
	int CrossoverPoint[2], CrossoverParticle, Temp;
	Phrase_Class TempPhrase;

	for(int i=0; i<ParticleNum; i++) //跑Particle
	{
		//如果要交配
		if( RandRange(0,1) < CrossoverRate )
		{
			CrossoverParticle = RandRange(0,ParticleNum-1);
			CrossoverPoint[0] = RandRange(0,3);
			CrossoverPoint[1] = RandRange(0,3);

			//如果交配點第一個大於第二個
			if(CrossoverPoint[0] > CrossoverPoint[1])
			{
                //對調
				Temp = CrossoverPoint[0];
				CrossoverPoint[0] = CrossoverPoint[1];
				CrossoverPoint[1] = Temp;
			}

			for(int j=0; j<4; j++) //跑Phrase
			{
				Application->ProcessMessages();
				if( j >= CrossoverPoint[0] &&  j <= CrossoverPoint[1] )
				{
					//對調
					TempPhrase = this->Particle[i].Phrase[j];
					this->Particle[i].Phrase[j] = this->Particle[CrossoverParticle].Phrase[j];
					this->Particle[CrossoverParticle].Phrase[j] = TempPhrase;
				}
            }
		}
	}
}

void Swarm_Class::Mutation(bool ChangeRate, int Epoch)
{
	float MutationRatePlus = 0;
	if(ChangeRate)
	{
		MutationRatePlus = 0.3 * Epoch / MaxEpoch;
	}

	for(int i=0; i<ParticleNum; i++) //跑Particle
	{
		for(int j=0; j<4; j++) //跑Phrase
		{
			for(int k=0; k<OneSectionNoteNum; k++) //Note
			{
				Application->ProcessMessages();
				//如果要突變
				if( RandRange(0,1) < MutationRate + MutationRatePlus )
				{
					this->Particle[i].Phrase[j].Note[k].Live = RandRange(0,1) > 0.5 ? true : false;
					this->Particle[i].Phrase[j].Note[k].Pos = (int)(RandRange(0, 6) + 0.5);
				}
			}
		}
	}
}

void Swarm_Class::Survive()
{
	for(int Gi=0; Gi<BestParticleNum; Gi++) //跑Particle
	{
		Application->ProcessMessages();
		this->Particle[Gi] =  this->G_Best[Gi];
	}
}

void Swarm_Class::Partition_Mutation(int Epoch)
{
	for(int i=0; i<ParticleNum; i++) //跑Particle
	{
		for(int j=0; j<4; j++) //跑Phrase
		{
			Application->ProcessMessages();
			if( RandRange(this->MinPhraseValue, this->MaxPhraseValue) < (0.4 * (MaxEpoch-Epoch) / MaxEpoch) * this->Particle[i].Phrase[j].Phrase_Fitness )
			{
				this->Particle[i].Phrase[j] = this->G_Best[(int)RandRange(0,BestParticleNum)].Phrase[j];
			}
		}
	}
}
